use bytes::Bytes;
use regex::Regex;
use std::{sync::OnceLock, time::Duration};
use tools::utils::gen_id::get_now_duration;
use tracing::{error, trace};

use crate::sip2::utils::get_bytes_str;

use super::transport::TransportProtocol;

pub(crate) mod manager;
pub(crate) mod reg_cli;
pub(crate) mod reg_ser;

#[derive(Debug)]
pub enum SipRegEvent {
	RegistSuccess(SipRegisterUser),
	RegistLoginOut(SipRegisterUser),
	RegistFailure(String),
}

///一个具有通话权限制的用户.
///
/// 一般指一个话机或坐席
#[derive(Debug, Clone)]
pub struct SipRegisterUser {
	pub(crate) login_name: String,
	pub(crate) password: String,
	pub(crate) name: String,
	pub(crate) expires_timestamp: Duration,
	pub(crate) realm: String,
	pub(crate) tp: TransportProtocol,
}

impl SipRegisterUser {
	pub fn new(
		password: String,
		expires_duration: Duration,
		realm: String,
		tp: TransportProtocol,
	) -> Self {
		Self {
			login_name: String::default(),
			password,
			name: String::default(),
			expires_timestamp: get_now_duration() + expires_duration,
			tp,
			realm,
		}
	}

	pub fn login_name(&self) -> &str {
		&self.login_name
	}

	pub fn password(&self) -> &str {
		&self.password
	}
	pub fn name(&self) -> &str {
		&self.name
	}
	pub fn expires(&self) -> Duration {
		self.expires_timestamp
	}
	pub fn realm(&self) -> &str {
		&self.realm
	}

	pub fn overtime(&self) -> bool {
		get_now_duration() > self.expires_timestamp
	}
}

#[derive(Debug)]
pub(crate) struct AuthInfo<'a> {
	realm: &'a str,
	nonce: &'a str,
	qop: &'a str,
	cnonce: &'a str,
	nc: &'a str,
	username: &'a str,
	uri: &'a str,
	response: &'a str,
	algorithm: &'a str,
}

///拆Authorization字段 ...
///
/// 内容为(以空格分割):
/// Authorization: Digest username="13385476884", realm="183.218.88.21",
/// nonce="c7b38b3e-edd8-40c9-b29e-6452d3d32104", uri="sip:183.218.88.21:5080",
/// response="d1845bf7e503a04b4252e4ecbc9322a7",
///algorithm=MD5, cnonce="0bc5e8bc9a9341bda0bc4eae07653f06", qop=auth, nc=00000001
pub(crate) fn load_auth_field<'a>(bytes: &'a Bytes) -> AuthInfo<'a> {
	static REGEX: OnceLock<Regex> = OnceLock::new();
	let regex = REGEX.get_or_init(||
	  Regex::new("(\\w+)=\"?(.+?)\"?(, *|$)").unwrap()
	);
	let str = get_bytes_str(bytes);
	let mut auth = AuthInfo {
		realm: "",
		nonce: "",
		qop: "",
		cnonce: "",
		nc: "",
		username: "",
		uri: "",
		response: "",
		algorithm: "",
	};

	for (_, [name, value, _]) in regex.captures_iter(str).map(|c| c.extract()) {
		match name {
			"realm" => auth.realm = value,
			"nonce" => auth.nonce = value,
			"qop" => auth.qop = value,
			"cnonce" => auth.cnonce = value,
			"nc" => auth.nc = value,
			"username" => auth.username = value,
			"uri" => auth.uri = value,
			"response" => auth.response = value,
			"algorithm" => auth.algorithm = value,
			_ => {}
		}
	}

	auth
}

pub(crate) fn verify(auth: &AuthInfo, user: &SipRegisterUser) -> bool {
	trace!("校验消息:{auth:?},user:{user:?}");
	calc_response(&auth, &user.password) == auth.response
}

pub(crate) fn calc_response(auth: &AuthInfo, password: &str) -> String {
	if !auth.algorithm.is_empty() && auth.algorithm != "MD5" {
		error!("不是MD5算法..直接返回");
		return String::default();
	}
	let h1_s = format!("{}:{}:{}", auth.username, auth.realm, password);
	let h1 = format!("{:x}", md5::compute(h1_s));

	let h2_s = format!("REGISTER:{}", auth.uri);
	let h2 = format!("{:x}", md5::compute(h2_s));

	let response_s = format!(
		"{}:{}:{}:{}:{}:{}",
		h1, auth.nonce, auth.nc, auth.cnonce, auth.qop, h2
	);

	format!("{:x}", md5::compute(response_s))
}

#[test]
fn test() {
	// let str = r#"Digest username="13385476884", realm="183.218.88.21", nonce="c7b38b3e-edd8-40c9-b29e-6452d3d32104", uri="sip:183.218.88.21:5080", response="d1845bf7e503a04b4252e4ecbc9322a7", algorithm=MD5, cnonce="0bc5e8bc9a9341bda0bc4eae07653f06", qop=auth, nc=00000001"#;
	// let str = r#"Digest username="13287241234", realm="183.218.88.21", nonce="d0027e2b-6206-4182-aa1d-b6b7f6401310", uri="sip:183.218.88.21:5080", response="08b9521655bc5fd372b88f96957f9838", algorithm=MD5, cnonce="3611169018714958b4917b8eae2a60ad", qop=auth, nc=00000001"#;
	let str = r#"Digest realm="8888888", nonce="QJkAlmcxf3AvFOWx", algorithm=MD5, username="admin",  uri="sip:127.0.0.1:3456", response="14342777f73a3480a87c9e979efea6dc", cnonce="u7tPylliimXdKeVC", nc=00000001, qop=auth"#;
	let bufs = Bytes::copy_from_slice(str.as_bytes());
	let auth = load_auth_field(&bufs);
	// 	let auth = AuthInfo{
	//     realm: "8888888",
	//     nonce: "QJkAlmcxf3AvFOWx",
	//     qop: "auth",
	//     cnonce: 	"u7tPylliimXdKeVC",
	//     nc: "00000001",
	//     username: "admin",
	//     uri: "sip:127.0.0.1:3456",
	//     response: "14342777f73a3480a87c9e979efea6dc",
	//     algorithm: "MD5",
	// };
	println!("auth:{:?}", auth);

	println!("resp:{}", calc_response(&auth, "admin"));
	assert_eq!(calc_response(&auth, "admin"), auth.response);
}

#[test]
fn test_regex() {
	let re = Regex::new("(\\w+)=\"?(.+?)\"?(, *|$)").unwrap();
	let str = r#"Digest username="13385476884", realm="183.218.88.21", nonce="c7b38b3e-edd8-40c9-b29e-6452d3d32104", uri="sip:183.218.88.21:5080", response="d1845bf7e503a04b4252e4ecbc9322a7", algorithm=MD5, cnonce="0bc5e8bc9a9341bda0bc4eae07653f06", qop=auth, nc=00000001"#;

	for (_, [name, value, _]) in re.captures_iter(str).map(|c| c.extract()) {
		println!("{:?},{:?}", name, value);
	}
}
